import pandas as pd
import json
import re

# 读取历史记录
g_record_history = {}
# 从文件中读取当前记录
g_record_now = {}
# 全局配置
g_cfg = {}

# 1. 历史记录
def read_history():
    global g_record_history

    try:
        with open('record_history.json', 'r', encoding='utf-8') as f:
            g_record_history = json.load(f if f else None)
            if not g_record_history:
                print("历史记录为空")
                return None
            return g_record_history
    except FileNotFoundError:
        print("历史记录文件不存在")
        return None
    
def write_history():
    global g_record_now

    try:
        with open('record_history.json', 'w', encoding='utf-8') as f:
            json.dump(g_record_now, f)
            print("写入历史记录成功")
    except FileNotFoundError:
        print("写入历史记录失败")

# 2. 计算旷课/请假次数

'''
计算班级里每个学生的旷课\请假次数
'''
def count_absent_times(df):
    stu_dic = {}

    for stus in df:
        if pd.isnull(stus):
            continue
        stus = re.split(r'[,，]', stus)
        for stu in stus:
            stu = stu.strip()
            if stu in stu_dic:
                stu_dic[stu] += 1
            else:
                stu_dic[stu] = 1
    
    return stu_dic


def sort_dic(dic):
    return sorted(dic.items(), key=lambda x: x[1], reverse=True)

def print_beautiful(namelist, title):
    print(title)
    for item in namelist:
        print("%-*s: %15s" %(15+len(item[0])-len(item[0].encode("gbk")),item[0], item[1]))
    

# 读取excel文件, 计算某一个班的旷课\请假次数
# file_path: excel文件路径
# sheet_name: sheet名字
def class_n_msg(file_path, sheet_name):
    try:
        df = pd.read_excel(file_path, sheet_name=sheet_name)

        absent = count_absent_times(df['旷课名单'])

        askleave = count_absent_times(df['请假名单'])

        return absent, askleave
    except:
        print("读取%s班级信息失败" %sheet_name)
        exit(1)



# 读取配置文件, 配置文件应有两个字段: file_path, sheet_names
# file_path: excel文件路径
# sheet_names: sheet名字列表
def read_json_cfg():
    try:
        with open('config.json', 'r', encoding='utf-8') as conf:
        
            cfg = json.load(conf if conf else None)

            if not cfg:
                print("配置文件为空")
                return None
            else:
                if 'file_path' not in cfg:
                    print("配置文件缺少file_path字段")
                    return None
                if 'sheet_names' not in cfg:
                    print("配置文件缺少sheet_names字段")
                    return None

        return cfg
    
    except FileNotFoundError:
        print("配置文件不存在")
        return None
    
# 读取旷课名单和请假名单
def read_absent_list():
    global g_cfg
    global g_record_now

    g_cfg = read_json_cfg()
    if not g_cfg:
        print("配置文件读取失败，退出")
        exit(1)

    file_path = g_cfg['file_path']
    sheet_names = g_cfg['sheet_names']
    for sheet_name in sheet_names:
        absent, askleave = class_n_msg(file_path, sheet_name)
        g_record_now[sheet_name] = {'absent': absent, 'askleave': askleave}

    return g_record_now

# 查看旷课名单
def view_abs():
    global g_cfg
    global g_record_now

    if not g_record_now:
        g_record_now = read_absent_list()

    sheet_names = g_cfg['sheet_names']
    for sheet_name in sheet_names:
        print("===================%s===================" %sheet_name)
        print_beautiful(sort_dic(g_record_now[sheet_name]['absent']), "旷课名单")
        print("----------------------------------------\n")
        print_beautiful(sort_dic(g_record_now[sheet_name]['askleave']), "请假名单")
        print("\n")

    
    

# 查看有变化的记录
# 读取当前的记录, 与历史记录比较, 输出有变化的记录
# 如果g_record_now不为空，则证明已经读取过了，无需再次读取
# 如果g_record_history为空, 则直接输出当前记录
def view_diff():
    global g_cfg
    global g_record_now
    global g_record_history

    if not g_record_now:
        g_record_now = read_absent_list()

    if not g_record_history:
        print("历史记录为空")
        view_abs()
        return
    
    # 对比两个记录，输出有变化的记录
    sheet_names = g_cfg['sheet_names']
    for sheet_name in sheet_names:
        print("===================%s===================" %sheet_name)
        print("旷课名单变化:")
        for stu in g_record_now[sheet_name]['absent']:
            if stu not in g_record_history[sheet_name]['absent'] or g_record_now[sheet_name]['absent'][stu] != g_record_history[sheet_name]['absent'][stu]:
                print("%-10s %-10s" %(stu, g_record_now[sheet_name]['absent'][stu]))

        print("----------------------------------------\n")
        
        print("请假名单变化:")
        for stu in g_record_now[sheet_name]['askleave']:
            if stu not in g_record_history[sheet_name]['askleave'] or g_record_now[sheet_name]['askleave'][stu] != g_record_history[sheet_name]['askleave'][stu]:
                print("%-10s %-10s" %(stu, g_record_now[sheet_name]['askleave'][stu]))
        print("\n")
    

# 选择菜单
def choose():
    print("请选择操作:")
    print("1. 查看旷课名单")
    print("2. 查看有变化的记录")
    print("3. 存储历史记录")
    print("4. 退出")
    return input("请输入:")
    

if __name__ == '__main__':
    # 首先读取历史记录
    g_record_history = read_history()

    while True:
        choice = choose()
        if choice == '1':
            view_abs()
        elif choice == '2':
            view_diff()
        elif choice == '3':
            write_history()
        elif choice == '4':
            break
        else:
            print("输入有误，请重新输入")
            continue
        